﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using com.lib.events;
using Lib.Scripts.NetWork;
namespace com.lib.net
{
    //Event 10-30
    public class TcpNetWork : MonoBehaviour
    {
        public static TcpNetWork Instance = null;
        [HideInInspector]
        public string ip;
        [HideInInspector]
        public int port;

        private Thread threa;

        private List<object> socket_Data = new List<object>();

        public bool Debug = true;

        void Awake()
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
            //threa = new Thread(StartUpdateThread);
            //threa.Start();
        }


        private void StartUpdateThread()
        {
            while (true)
            {
                if (socket_Data.Count > 0)
                {
                    var data = socket_Data[0];
                    var array = data as Params;
                    Send(array.Get("id").getInt(), Encoding.UTF8.GetBytes(array.data.ToJson().Encode()));
                    socket_Data.RemoveAt(0);
                }
            }
        }

        public void Send(object data)
        {
            if (NetData.TcpInit == false)
            {
                Logger.LogError("Please Call NetWorks.Init At NetWorks Line 28");
                return;
            }
            if (NetData.CanSend == false)
            {
               // Logger.LogError("Net Not Connection 36");
                return;
            }
            var array = data as Params;
            Send(array.Get("id").getInt(), Encoding.UTF8.GetBytes(array.data.ToJson().Encode()));
           
        }

        void OnDestroy()
        {

            Close();

        }

        public void Close()
        {
            if (TcpData.socket != null)
            {
                TcpData.socket.Close(); TcpData.socket = null;
            }
            if (TcpData.thread != null) { TcpData.thread.Abort(); }
            threa.Abort();
            
        }

        /// <summary>
        /// Connection?
        /// </summary>
        /// <param name="_ip"></param>
        /// <param name="_port"></param>
        /// <param name="tempCall"></param>
        public void Init(string _ip, int _port, NetWorks.NetCall tempCall)
        {
            if (_ip.Equals(""))
            {
                Logger.LogError("Please Enter The IpAddress");
                return;
            }
            EventLib.Instance.RegisterEvent(10, delegate(object o) { tempCall(o); });
            ip = _ip;
            port = _port;
            NetData.TcpInit = true;
            ResetConnection();
           
        }

        #region TCP连接函数
        /// <summary>
        /// 链接
        /// </summary>
        private void ResetConnection()
        {
            if (TcpData.thread != null)
            {
                TcpData.thread.Abort();
            }
            if (TcpData.socket != null)
            {
                new Thread(ThreadDo).Start();
            }
            else
            {
                new Thread(ThreadOnConnec).Start();
            }
        }


        private void ThreadOnConnec()
        {
            try
            {
                var endPort = new IPEndPoint(IPAddress.Parse(ip), port);
                TcpData.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                TcpData.socket.Connect(endPort);
                TcpCallBackData t = new TcpCallBackData();
                NetData.CanSend = true;
                t.type = TcpCallType.Success;
                t.data = "网络连接成功!";
                EventLib.Instance.SendEvent(10, t);
                StartReveive();
            }
            catch (Exception e)
            {
                TcpCallBackData t = new TcpCallBackData();
                t.type = TcpCallType.Fail;
                t.data = "网络连接失败!";
                EventLib.Instance.SendEvent(10, t);
                NetData.CanSend = false;
            }
        }


        private void ThreadDo()
        {
            try
            {
                var endPort = new IPEndPoint(IPAddress.Parse(ip), port);
                TcpData.socket.Connect(endPort);
                TcpCallBackData t = new TcpCallBackData();
                NetData.CanSend = true;
                t.type = TcpCallType.Success;
                t.data = "网络连接成功!";
                EventLib.Instance.SendEvent(10, t);
                StartReveive();
            }
            catch (Exception e)
            {
                NetData.CanSend = false;
                TcpCallBackData t = new TcpCallBackData();
                t.type = TcpCallType.Fail;
                t.data = "网络连接失败!";
                EventLib.Instance.SendEvent(10, t);
            }

        }
        #endregion
 
        /// <summary>
        /// 消息发送
        /// </summary>
        /// <param name="id"></param>
        /// <param name="data"></param>
        public void Send(int id,byte[] data)
        {
            try
            {
                var result = new TooleMessage(1, 1, data.Length, data);
                if (TcpData.socket != null)
                {
                    TcpData.socket.Send(result.ToBytes());
                }

            }
            catch (Exception e)
            {
                TcpCallBackData t = new TcpCallBackData();
                t.type = TcpCallType.Fail;
                t.data = "消息发送失败!"+e.Message;
                EventLib.Instance.SendEvent(10, t);
                NetData.CanSend = false;
            }
        }

        #region TCP 接受函数
        private void StartReveive()
        {
            TooleMessageStream messageStream = new TooleMessageStream();
            while (true)
            {
                try
                {
                    const int bufLen = 10240;
                    var buffer = new byte[bufLen];
                    var recvLen = TcpData.socket.Receive(buffer, 0, bufLen, SocketFlags.None);
                    if (recvLen == 0)
                    {
                        TcpCallBackData t = new TcpCallBackData();
                        t.type = TcpCallType.Fail;
                        t.data = "接受失败!";
                        EventLib.Instance.SendEvent(10, t);
                        NetData.CanSend = false;
                        break;
                    }
                    messageStream.Write(buffer, 0, recvLen);
                     TooleMessage message;
                     while (messageStream.Read(out message))
                     {
                         var buf = new byte[message.CommandSize];
                         Buffer.BlockCopy(message.Content, 0, buf, 0, message.CommandSize);
                         var tempCall = Encoding.UTF8.GetString(buf);
                         if (Debug) { Logger.Log(tempCall); }
                         TcpReceiveData t = new TcpReceiveData();
                         
                         var json = ToolsLib.LuaParseJson(tempCall);
                         t.param = json;
                         t.Cmd = json.Get("C").getInt();
                         TcpCallBackData t1 = new TcpCallBackData();
                         t1.type = TcpCallType.Receive;
                         t1.data = t;
                         EventLib.Instance.SendEvent(10, t1);
                     }
                }
                catch (Exception)
                {
                    TcpCallBackData t = new TcpCallBackData();
                    t.type = TcpCallType.Fail;
                    t.data = "接受失败!";
                    EventLib.Instance.SendEvent(10, t);
                    NetData.CanSend = false;

                    break;
                }
            }
        }
        #endregion
    }
}